package vsvm.classifier;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;

import vsvm.gui.IActionsProvider;
import vsvm.math.CoreMath;

public abstract class AbstractTestSet implements IActionsProvider, Serializable {

	
	public abstract void execute();
	
	protected String name;
	protected ArrayList<TestCase> testCases;
	protected Double positiveClass = null;
	protected Double negativeClass = null;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String toString() {
		return name;
	}
	
	public Iterator <TestCase> getTestCases() {
		return testCases.iterator();
	}
	
	public int getTestCasesCount() {
		return testCases.size();
	}
	
	public double getPositiveClass() {
		
		if (this.positiveClass == null)
			this.findNegativesPositives();
		
		return this.positiveClass;
	}
	
	public double getNegativeClass() {
		if (this.negativeClass == null)
			this.findNegativesPositives();
		
		return this.negativeClass;
	}
	
	private void findNegativesPositives() {
		double positive = 1;
		double negative = testCases.get(0).getActualClass();
		
		int n = testCases.size();
		
		for (int i = 1; i < n; i++) {
			double current = testCases.get(i).getActualClass();
			if (Math.abs(current - negative) < 1e-8) continue;
			if (negative < current) {
				positive = current;
				break;
			} else if (negative > current) {
				positive = negative;
				negative = current;
				break;
			}
		}
		
		this.positiveClass = new Double(positive);
		this.negativeClass = new Double(negative);
	}
	
	public int getActualPositivesCount() {
		double positive = this.getPositiveClass();
		
		int pcount = 0;		
		
		Iterator <TestCase> it = this.getTestCases();
		
		while (it.hasNext()) {
			TestCase tcase = it.next();
			if (Math.abs(tcase.getActualClass() - positive) < CoreMath.EPS) pcount++;							
		}
		
		return pcount;
	}
	
	public int getActualNegativesCount() {
		double negative = this.getNegativeClass();
		
		int ncount = 0;		
		
		Iterator <TestCase> it = this.getTestCases();
		
		while (it.hasNext()) {
			TestCase tcase = it.next();
			if (Math.abs(tcase.getActualClass() - negative) < CoreMath.EPS) ncount++;							
		}
		
		return ncount;
	}
	
	public double getAccuracy() {
		int ncount = 0, pcount = 0;		
		
		Iterator <TestCase> it = this.getTestCases();
		
		while (it.hasNext()) {
			TestCase tcase = it.next();
			if (Math.abs(tcase.getActualClass() - tcase.getPredictedClass()) < CoreMath.EPS) pcount++;
			else ++ncount;
		}
		
		return (double)pcount/((double)(pcount + ncount));
		
	}
}
